package org.budo.graph.service.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.budo.graph.view.util.DruidDataSourceUtil;
import org.budo.support.java.net.util.JavaNetUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.time.Time;
import org.springframework.beans.factory.BeanIsAbstractException;
import org.springframework.context.ApplicationContext;

import com.alibaba.druid.stat.DruidStatService;
import com.alibaba.druid.util.Utils;
import com.alibaba.dubbo.registry.RegistryService;
import com.alibaba.dubbo.rpc.service.EchoService;

/**
 * @author lmw
 */
public class BudoMetricUtil {
    public static String budoMetric(ApplicationContext applicationContext, String url) {
        String result = "{" //
                + "\"ip\":[" + StringUtil.join(JavaNetUtil.getIpAddresses(), ",", "\"", "\"") + "]," //
                + "\"startAt\":\"" + Time.when(Utils.getStartTime()).toString("yyyy-MM-dd HH:mm:ss") + "\"," //
                + "\"druidActiveCount\":" + DruidDataSourceUtil.druidActiveCount(applicationContext) + "," //
                + "\"totalMemory\":" + Runtime.getRuntime().totalMemory();

        Map<String, String> parameters = DruidStatService.getParameters(url);
        String dubbo = parameters.get("dubbo");

        if (!StringUtil.equals("false", dubbo)) { // 默认开
            Map<String, String> dubboServicePackages = dubboServicePackages(applicationContext);
            result += ",\"dubboServicePackages\":[" + StringUtil.join(dubboServicePackages.values(), ",", "\"", "\"") + "]";
        }

        result += "}";

        return result;
    }

    private static Map<String, String> dubboServicePackages(ApplicationContext applicationContext) {
        Map<String, String> packageMap = new HashMap<String, String>(); // 每个 package 里只检查一个接口

        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            Object bean = null;
            try {
                bean = applicationContext.getBean(beanName);
            } catch (BeanIsAbstractException e) {
                continue;
            } catch (Throwable e) {
                throw new RuntimeException("#148 getBean error, beanName=" + beanName, e);
            }

            if (!(bean instanceof EchoService)) {
                continue;
            }

            if (bean instanceof RegistryService) {
                continue;
            }

            List<String> interfaceNames = DubboEchoUtil.getBeanInterfaceNames(bean);
            if (null == interfaceNames || interfaceNames.isEmpty()) {
                continue;
            }

            // 取第一个
            String interfaceName = interfaceNames.get(0) + "";
            int lastDot = interfaceName.lastIndexOf('.');
            String interfacePackageName = interfaceName.substring(0, lastDot);

            // 检查过这个package了
            if (packageMap.containsKey(interfacePackageName)) {
                continue;
            }

            packageMap.put(interfacePackageName, interfaceName); // 正常的package

            try {
                ((EchoService) bean).$echo("echo success");
            } catch (Throwable e) {
                if (StringUtil.contains("" + e, "No provider available") //
                        || StringUtil.contains("" + e, "RpcException: Failed to invoke")) {
                    throw new IllegalStateException("#73 dubbo no provider, interfaceName=" + interfaceName + ", e=" + e);
                }

                throw new IllegalStateException("#76 dubbo provider $echo error, interfaceName=" + interfaceName + ", e=" + e, e);
            }
        }
        return packageMap;
    }
}